import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/common/prisma/PrismaService';
import NoticeQueryParam from '../param/NoticeQueryParam';
import NoticeDto from '../dto/NoticeDto';
import { plainToInstance } from 'class-transformer';
import { Util } from 'src/common/Util';
import EventTypeEnum from 'src/common/enum/EventTypeEnum';
import { OnEvent } from '@nestjs/event-emitter';
import ServiceException from 'src/common/ServiceException';
import BaseEvent from 'src/common/event/BaseEvent';

/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-29 17:08:01
 * @LastEditTime: 2024-12-04 13:14:52
 * @Description: 系统通知
 */
@Injectable()
class NoticeService {
  constructor(private prisma: PrismaService) {}

  async list(param: NoticeQueryParam) {
    const skip = param.pageNum != 0 ? (param.pageNum - 1) * param.pageSize : 0;
    const whereClause: any = this.generatePageQueryCondition(param);
    const [total, list] = await this.prisma.$transaction([
      this.prisma.sysNotice.count({ where: whereClause }),
      this.prisma.sysNotice.findMany({
        skip,
        take: param.pageSize,
        orderBy: {
          createTime: 'desc',
        },
        where: whereClause,
      }),
    ]);
    const rows: NoticeDto[] = plainToInstance(NoticeDto, list);
    return {
      total,
      rows,
    };
  }
  generatePageQueryCondition(param: NoticeQueryParam): any {
    const whereClause: any = {};
    whereClause.noticeType = {
      in: ['1', '2'],
    };
    if (param.noticeTitle) {
      whereClause.noticeTitle = {
        contains: param.noticeTitle,
      };
    }

    if (param.createBy) {
      whereClause.createBy = {
        contains: param.createBy,
      };
    }

    if (param.noticeType !== undefined) {
      whereClause.noticeType = param.noticeType;
    }
    return whereClause;
  }

  async deleteNotice(id: number) {
    await this.prisma.sysNotice.delete({
      where: {
        noticeId: id,
      },
    });
  }

  async detail(id: number) {
    const sysNotice = await this.prisma.sysNotice.findUnique({
      where: {
        noticeId: id,
      },
    });
    return plainToInstance(NoticeDto, sysNotice);
  }

  async createNotice(notice: NoticeDto) {
    if (notice.startTime) {
      notice.startTime = Util.convertUTCToLocalTime(new Date(notice.startTime));
    }
    if (notice.endTime) {
      notice.endTime = Util.convertUTCToLocalTime(new Date(notice.endTime));
    }
    await this.prisma.sysNotice.create({
      data: {
        noticeTitle: notice.noticeTitle,
        noticeType: notice.noticeType,
        noticeContent: notice.noticeContent
          ? Buffer.from(notice.noticeContent)
          : null,
        status: notice.status,
        startTime: notice.startTime,
        endTime: notice.endTime,
      },
    });
  }
  async updateNotice(notice: NoticeDto) {
    if (notice.startTime) {
      notice.startTime = Util.convertUTCToLocalTime(new Date(notice.startTime));
    }
    if (notice.endTime) {
      notice.endTime = Util.convertUTCToLocalTime(new Date(notice.endTime));
    }
    await this.prisma.sysNotice.update({
      where: {
        noticeId: notice.noticeId,
      },
      data: {
        noticeTitle: notice.noticeTitle,
        noticeType: notice.noticeType,
        noticeContent: notice.noticeContent
          ? Buffer.from(notice.noticeContent)
          : null,
        status: notice.status,
        startTime: notice.startTime,
        endTime: notice.endTime,
      },
    });
  }

  /**
   * 获取所有通知，状态正常，时间有效的通知
   */
  async getAllNotice() {
    const now = Util.getCurrentLocalTime();
    const sysNotice = await this.prisma.sysNotice.findMany({
      where: {
        status: '0',
        startTime: {
          lte: now,
        },
        endTime: {
          gte: now,
        },
      },
    });
    return plainToInstance(NoticeDto, sysNotice);
  }

  async getUserNotice(userId: number) {
    // 查询 noticeType 为3的用户私信
    const sysNotices = await this.prisma.sysNotice.findMany({
      where: {
        noticeType: '3',
        userId: userId,
        status: '0',
      },
      orderBy: {
        noticeId: 'desc',
      },
    });
    if (!sysNotices || sysNotices.length === 0) {
      return new NoticeDto();
    }
    const noticeDtos = plainToInstance(NoticeDto, sysNotices);
    const latestNotice = noticeDtos[noticeDtos.length - 1];
    latestNotice.msgCount = noticeDtos.length;
    return latestNotice;
  }

  async findUserNoticeList(param: NoticeQueryParam) {
    const skip = param.pageNum != 0 ? (param.pageNum - 1) * param.pageSize : 0;
    const whereClause: any = this.generateUserNoticePageQueryCondition(param);
    const [total, list] = await this.prisma.$transaction([
      this.prisma.sysNotice.count({ where: whereClause }),
      this.prisma.sysNotice.findMany({
        skip,
        take: param.pageSize,
        orderBy: {
          noticeId: 'desc',
        },
        where: whereClause,
      }),
    ]);
    const rows: NoticeDto[] = plainToInstance(NoticeDto, list);
    return {
      total,
      rows,
    };
  }
  private generateUserNoticePageQueryCondition(param: NoticeQueryParam): any {
    const whereClause: any = {};
    whereClause.userId = param.userId;
    whereClause.noticeType = {
      in: ['3'],
    };
    if (param.noticeTitle) {
      whereClause.noticeTitle = {
        contains: param.noticeTitle,
      };
    }

    if (param.createBy) {
      whereClause.createBy = {
        contains: param.createBy,
      };
    }

    if (param.status !== undefined) {
      whereClause.status = param.status;
    }
    return whereClause;
  }

  async readUserNoticeSingle(userId: number, noticeId: number) {
    if (!noticeId) return;
    await this.prisma.sysNotice.update({
      where: {
        noticeId: noticeId,
        userId: userId,
      },
      data: {
        status: '1',
      },
    });
  }
  async readUserNoticeAll(userId: number) {
    await this.prisma.sysNotice.updateMany({
      where: {
        userId: userId,
      },
      data: {
        status: '1',
      },
    });
  }

  @OnEvent(EventTypeEnum.BUSINESS_MESSAGE_NOTICE)
  async handelUserNoticeMsg(event: BaseEvent<NoticeDto>) {
    const notice = event.getData();
    //通知入库
    if (!notice.noticeTitle) {
      throw new ServiceException('消息通知标题不能为空');
    }
    if (!notice.userId) {
      throw new ServiceException('消息通知用户不能为空');
    }
    await this.prisma.sysNotice.create({
      data: {
        noticeTitle: notice.noticeTitle,
        noticeType: notice.noticeType,
        noticeContent: notice.noticeContent
          ? Buffer.from(notice.noticeContent)
          : null,
        status: notice.status,
        userId: notice.userId,
      },
    });
  }
}
export default NoticeService;
